/*
 *  Copyright (C) 2010 Glauco
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.bindings;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.balisunrise.application.Application;
import org.balisunrise.common.BindingException;
import org.balisunrise.common.BindingGroup;

/**
 *
 * @author glacuo
 */
public class DefaultBindingGroup implements BindingGroup<Binding>, Serializable{

    private ArrayList<Binding> bindings;

    private Map<Object, BindingPropertyListener> bpls;

    private boolean vinculado;

    public DefaultBindingGroup(){
        bindings = new ArrayList<Binding>();
        bpls = new HashMap<Object, BindingPropertyListener>();
        vinculado = false;
    }

    private BindingPropertyListener getBPL(Object key){

        if(bpls.containsKey(key))
            return bpls.get(key);

        try{
            BindingPropertyListener bpl =
                    new BindingPropertyListener(null, key);
            bpls.put(key, bpl);
            return bpl;
        }catch(BindingException ex){
            Application.get().getLogger().log(Level.SEVERE,
                    "BindingGroup não pode construir um BindingPropertyListener"
                    , ex);
        }

        return null;
    }

    @Override
    public void addBinding(Binding binding){

        if(binding == null)
            return ;

        // se não contém
        if(!bindings.contains(binding)){

            // verifica se tem uma trigger para o source
            if (binding.getSourceTrigger() == null){
                Object source = binding.getSource();
                BindingPropertyListener bpl = getBPL(source);
                bpl.addBinding(binding.getSourceProperty(), binding,
                        BindingPropertyListener.SOURCE);
                binding.setSourceTrigger(bpl);
            }

            // verifica se tem uma trigger para o target
            if (binding.getTargetTrigger() == null){
                Object target = binding.getTarget();
                BindingPropertyListener bpl = getBPL(target);
                bpl.addBinding(binding.getTargetProperty(), binding,
                        BindingPropertyListener.TARGET);
                binding.setTargetTrigger(bpl);
            }

            bindings.add(binding);
        }

        if(vinculado)
            binding.bind();
    }

    @Override
    public void removeBinding(Binding binding){

        for (BindingPropertyListener bpl : bpls.values()) {
            bpl.removeBinding(binding);
        }

        bindings.remove(binding);
    }

    public void removeBinding(int index){
        if(index >= 0 && bindings.size() > index)
            removeBinding(bindings.get(index));
    }

    @Override
    public List<Binding> getBindings(){
        return bindings;
    }

    @Override
    public void bind(){
        if(vinculado)
            return ;

        for (Binding binding : bindings) {
            binding.bind();
        }

        vinculado = true;
    }

    @Override
    public void unbind(){
        if(!vinculado)
            return ;

        for (Binding binding : bindings) {
            binding.unBind();
        }

        vinculado = false;
    }

    @Override
    public Binding getBinding(String name) {
        return null;
        //throw new UnsupportedOperationException("Not supported yet.");
    }
}
